package com;

import java.util.concurrent.CountDownLatch;

public class 用代码来证明一级缓存和二级缓存的存在 {
    // 定义一个一亿的数字作为我们的循环次数
    public static long COUNT = 1_0000_0000L;
    private static class T{
        /**
         * 我们的这个类中前面是7个long类型，共56字节，中间是一个8字节的long类型，后面是7个long的56字节的类型
         * 所以在这个代码中的x无论与前面组合，与后面组合，还是自己单独组合，都不能与数组中的另外一个x位于同一行
         * 这个时候我们的x变量就可以分别取出，放到两个缓存中进行修改，不需要互相通知，所以效率比较高
         */
        public long p1,p2,p3,p4,p5,p6,p7; // 此处占用7*8=56字节
        public volatile long x = 0L;        // 此处占用8字节
        public long p9,p10,p11,p12,p13,p14,p15; // 此处占用7*8=56字节
    }
    private static class K{
        /**
         * 在这里的代码中两个K中的x都是8字节，总共16字节，我们的缓存行是64自己，所以极有可能把这两个x放到同一个
         * 缓存行中，这个时候就把这一行同时放到了第一个和第二个CPU中，让后CPU1修改之后同时修改CPU2，CPU2修改之后
         * 通知CPU1，运行一边就重新读一遍，互相修改之后造成了性能的降低
         */
        public volatile long x = 0L;        // 此处占用8字节
    }
    public static T[] arr1=new T[2];
    public static K[] arr2=new K[2];
    static{
        arr1[0] = new T();
        arr1[1] = new T();
        arr2[0] = new K();
        arr2[1] = new K();
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch1 = new CountDownLatch(2);
        CountDownLatch latch2 = new CountDownLatch(2);
        Thread t1 = new Thread(() -> {
            for (long i = 0; i < COUNT; i++) {
                arr1[0].x = i;
            }
            latch1.countDown();
        });
        Thread t2 = new Thread(() -> {
            for (long i = 0; i < COUNT; i++) {
                arr1[1].x = i;
            }
            latch1.countDown();
        });
        Thread t3 = new Thread(() -> {
            for (long i = 0; i < COUNT; i++) {
                arr2[0].x = i;
            }
            latch2.countDown();
        });
        Thread t4 = new Thread(() -> {
            for (long i = 0; i < COUNT; i++) {
                arr2[1].x = i;
            }
            latch2.countDown();
        });
        // 计算T的线程循环用时(相对用时短)
        final long start1 = System.nanoTime();
        t1.start();
        t2.start();
        latch1.await();
        System.out.println((System.nanoTime() - start1)/100_0000);
        // 计算K的线程循环用时(相对用时长)
        final long start2 = System.nanoTime();
        t3.start();
        t4.start();
        latch2.await();
        System.out.println((System.nanoTime() - start2)/100_0000);
    }
}
